home *** CD-ROM | disk | FTP | other *** search
- # -*- coding: utf-8 -*-
- #
- # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- #
- # Author: Don Welch
- #
-
- from __future__ import generators
-
- # Std Lib
- import sys
- import os
- import os.path
- import time
- import threading
- import Queue
- from cStringIO import StringIO
-
- # Local
- from base.g import *
- from base.codes import *
- from base import device, utils, status, pml
-
- # Event queue values (UI ==> Copy thread)
- COPY_CANCELED = 1
-
- # Update queue values (Copy thread ==> UI)
- STATUS_IDLE = 0
- STATUS_SETTING_UP = 1
- STATUS_WARMING_UP = 2
- STATUS_ACTIVE = 3
- STATUS_DONE = 4
- STATUS_ERROR = 5
-
-
- # PML Copier Only
- class PMLCopyDevice(device.Device):
- def __init__(self, device_uri=None, printer_name=None,
- service=None, callback=None):
-
- device.Device.__init__(self, device_uri, printer_name,
- service, callback)
-
- self.copy_thread = None
-
- def copy(self, num_copies=1, contrast=0, reduction=100,
- quality=pml.COPIER_QUALITY_NORMAL,
- fit_to_page=pml.COPIER_FIT_TO_PAGE_ENABLED,
- scan_style=SCAN_STYLE_FLATBED,
- update_queue=None, event_queue=None):
-
- if not self.isCopyActive():
- self.copy_thread = PMLCopyThread(self, num_copies, contrast, reduction, quality,
- fit_to_page, scan_style, update_queue, event_queue)
- self.copy_thread.start()
- return True
- else:
- return False
-
- def isCopyActive(self):
- if self.copy_thread is not None:
- return self.copy_thread.isAlive()
- else:
- return False
-
- def waitForCopyThread(self):
- if self.copy_thread is not None and \
- self.copy_thread.isAlive():
-
- self.copy_thread.join()
-
-
-
- class PMLCopyThread(threading.Thread):
- def __init__(self, dev, num_copies, contrast, reduction, quality,
- fit_to_page, scan_style,
- update_queue=None, event_queue=None):
-
- threading.Thread.__init__(self)
- self.dev = dev
- self.num_copies = num_copies
- self.contrast = contrast
- self.reduction = reduction
- self.quality = quality
- self.fit_to_page = fit_to_page
- self.scan_style = scan_style
- self.event_queue = event_queue
- self.update_queue = update_queue
- self.prev_update = ''
- self.copy_type = self.dev.copy_type
- log.debug("Copy-type = %d" % self.copy_type)
-
- def run(self):
- STATE_DONE = 0
- STATE_ERROR = 5
- STATE_ABORTED = 10
- STATE_SUCCESS = 20
- STATE_BUSY = 25
- STATE_SET_TOKEN = 30
- STATE_SETUP_STATE = 40
- STATE_SETUP_PARAMS = 50
- STATE_START = 60
- STATE_ACTIVE = 70
- STATE_RESET_TOKEN = 80
-
- # state = STATE_SET_TOKEN
- state = STATE_SETUP_STATE
-
- while state != STATE_DONE: # ------------------------- Copier Thread
- # revisit - Checking cancel and setting state here means
- # every state can unconditionally transition to STATE_ABORTED.
- # This has not been verified.
- # if self.check_for_cancel():
- # state = STATE_ABORTED
-
- if state == STATE_ABORTED:
- log.debug("%s State: Aborted" % ("*"*20))
- self.write_queue(STATUS_DONE) # This was STATUS_ERROR.
- state = STATE_RESET_TOKEN
-
- if state == STATE_ERROR:
- log.debug("%s State: Error" % ("*"*20))
- self.write_queue(STATUS_ERROR)
- state = STATE_RESET_TOKEN
-
- elif state == STATE_SUCCESS:
- log.debug("%s State: Success" % ("*"*20))
- self.write_queue(STATUS_DONE)
- state = STATE_RESET_TOKEN
-
- elif state == STATE_BUSY:
- log.debug("%s State: Busy" % ("*"*20))
- self.write_queue(STATUS_ERROR)
- state = STATE_RESET_TOKEN
-
- elif state == STATE_SET_TOKEN:
- log.debug("%s State: Acquire copy token" % ("*"*20))
-
- self.write_queue(STATUS_SETTING_UP)
-
- try:
- result_code, token = self.dev.getPML(pml.OID_COPIER_TOKEN)
- except Error:
- log.debug("Unable to acquire copy token (1).")
- state = STATE_SETUP_STATE
- else:
- if result_code > pml.ERROR_MAX_OK:
- state = STATE_SETUP_STATE
- log.debug("Skipping token acquisition.")
- else:
- token = time.strftime("%d%m%Y%H:%M:%S", time.gmtime())
- log.debug("Setting token: %s" % token)
- try:
- self.dev.setPML(pml.OID_COPIER_TOKEN, token)
- except Error:
- log.error("Unable to acquire copy token (2).")
- state = STATUS_ERROR
- else:
- result_code, check_token = self.dev.getPML(pml.OID_COPIER_TOKEN)
-
- if check_token == token:
- state = STATE_SETUP_STATE
- else:
- log.error("Unable to acquire copy token (3).")
- state = STATE_ERROR
-
- elif state == STATE_SETUP_STATE:
- log.debug("%s State: Setup state" % ("*"*20))
-
- if self.copy_type == COPY_TYPE_DEVICE:
- result_code, copy_state = self.dev.getPML(pml.OID_COPIER_JOB)
-
- if copy_state == pml.COPIER_JOB_IDLE:
- self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_SETUP)
- state = STATE_SETUP_PARAMS
-
- else:
- state = STATE_BUSY
-
- elif self.copy_type == COPY_TYPE_AIO_DEVICE:
- result_code, copy_state = self.dev.getPML(pml.OID_SCAN_TO_PRINTER)
-
- if copy_state == pml.SCAN_TO_PRINTER_IDLE:
- state = STATE_SETUP_PARAMS
-
- else:
- state = STATE_BUSY
-
-
-
- elif state == STATE_SETUP_PARAMS:
- log.debug("%s State: Setup Params" % ("*"*20))
-
- if self.num_copies < 0: self.num_copies = 1
- if self.num_copies > 99: self.num_copies = 99
-
- if self.copy_type == COPY_TYPE_DEVICE: # MFP
-
- # num_copies
- self.dev.setPML(pml.OID_COPIER_JOB_NUM_COPIES, self.num_copies)
-
- # contrast
- self.dev.setPML(pml.OID_COPIER_JOB_CONTRAST, self.contrast)
-
- # reduction
- self.dev.setPML(pml.OID_COPIER_JOB_REDUCTION, self.reduction)
-
- # quality
- self.dev.setPML(pml.OID_COPIER_JOB_QUALITY, self.quality)
-
- # fit_to_page
- if self.scan_style == SCAN_STYLE_FLATBED:
- self.dev.setPML(pml.OID_COPIER_JOB_FIT_TO_PAGE, self.fit_to_page)
-
- else: # AiO
- # num_copies
- self.dev.setPML(pml.OID_COPIER_NUM_COPIES_AIO, self.num_copies)
-
- # contrast
- self.contrast = (self.contrast * 10 / 25) + 50
- self.dev.setPML(pml.OID_COPIER_CONTRAST_AIO, self.contrast)
-
- if self.fit_to_page == pml.COPIER_FIT_TO_PAGE_ENABLED:
- self.reduction = 0
-
- # reduction
- self.dev.setPML(pml.OID_COPIER_REDUCTION_AIO, self.reduction)
-
- # quality
- self.dev.setPML(pml.OID_COPIER_QUALITY_AIO, self.quality)
-
- self.dev.setPML(pml.OID_PIXEL_DATA_TYPE, pml.PIXEL_DATA_TYPE_COLOR_24_BIT)
- self.dev.setPML(pml.OID_COPIER_SPECIAL_FEATURES, pml.COPY_FEATURE_NONE)
- self.dev.setPML(pml.OID_COPIER_PHOTO_MODE, pml.ENHANCE_LIGHT_COLORS | pml.ENHANCE_TEXT)
-
- # tray select
- self.dev.setPML(pml.OID_COPIER_JOB_INPUT_TRAY_SELECT, pml.COPIER_JOB_INPUT_TRAY_1)
-
- # media type
- self.dev.setPML(pml.OID_COPIER_MEDIA_TYPE, pml.COPIER_MEDIA_TYPE_AUTOMATIC)
-
- # pixel data type
- self.dev.setPML(pml.OID_PIXEL_DATA_TYPE, pml.PIXEL_DATA_TYPE_COLOR_24_BIT)
-
- # special features
- self.dev.setPML(pml.OID_COPIER_SPECIAL_FEATURES, pml.COPY_FEATURE_NONE)
-
- # media size
- self.dev.setPML(pml.OID_COPIER_JOB_MEDIA_SIZE, pml.COPIER_JOB_MEDIA_SIZE_US_LETTER)
-
-
-
-
- log.debug("num_copies = %d" % self.num_copies)
- log.debug("contrast= %d" % self.contrast)
- log.debug("reduction = %d" % self.reduction)
- log.debug("quality = %d" % self.quality)
- log.debug("fit_to_page = %d" % self.fit_to_page)
-
- state = STATE_START
-
- elif state == STATE_START:
- log.debug("%s State: Start" % ("*"*20))
-
- if self.copy_type == COPY_TYPE_DEVICE:
- self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_START)
-
- elif self.copy_type == COPY_TYPE_AIO_DEVICE:
- self.dev.setPML(pml.OID_SCAN_TO_PRINTER, pml.SCAN_TO_PRINTER_START)
-
- state = STATE_ACTIVE
-
- elif state == STATE_ACTIVE:
- log.debug("%s State: Active" % ("*"*20))
-
- if self.copy_type == COPY_TYPE_DEVICE:
- while True:
- result_code, copy_state = self.dev.getPML(pml.OID_COPIER_JOB)
-
- if self.check_for_cancel():
- self.dev.setPML(pml.OID_COPIER_JOB, pml.COPIER_JOB_IDLE) # cancel
- state = STATE_ABORTED
- break
-
- if copy_state == pml.COPIER_JOB_START:
- log.debug("state = start")
- time.sleep(1)
- continue
-
- if copy_state == pml.COPIER_JOB_ACTIVE:
- self.write_queue(STATUS_ACTIVE)
- log.debug("state = active")
- time.sleep(2)
- continue
-
- elif copy_state == pml.COPIER_JOB_ABORTING:
- log.debug("state = aborting")
- state = STATE_ABORTED
- break
-
- elif copy_state == pml.COPIER_JOB_IDLE:
- log.debug("state = idle")
- state = STATE_SUCCESS
- break
-
- elif self.copy_type == COPY_TYPE_AIO_DEVICE:
- while True:
- result_code, copy_state = self.dev.getPML(pml.OID_SCAN_TO_PRINTER)
-
- if self.check_for_cancel():
- self.dev.setPML(pml.OID_SCAN_TO_PRINTER, pml.SCAN_TO_PRINTER_IDLE) # cancel
- state = STATE_ABORTED
- break
-
- if copy_state == pml.SCAN_TO_PRINTER_START:
- log.debug("state = start")
- time.sleep(1)
- continue
-
- if copy_state == pml.SCAN_TO_PRINTER_ACTIVE:
- self.write_queue(STATUS_ACTIVE)
- log.debug("state = active")
- time.sleep(2)
- continue
-
- elif copy_state == pml.SCAN_TO_PRINTER_ABORTED:
- log.debug("state = aborting")
- state = STATE_ABORTED
- break
-
- elif copy_state == pml.SCAN_TO_PRINTER_IDLE:
- log.debug("state = idle")
- state = STATE_SUCCESS
- break
-
-
- elif state == STATE_RESET_TOKEN:
- log.debug("%s State: Release copy token" % ("*"*20))
-
- try:
- self.dev.setPML(pml.OID_COPIER_TOKEN, '\x00'*16)
- except Error:
- log.error("Unable to release copier token.")
-
- self.dev.close() # Close the device.
-
- state = STATE_DONE
-
-
- def check_for_cancel(self):
- canceled = False
- while self.event_queue.qsize():
- try:
- event = self.event_queue.get(0)
- if event == COPY_CANCELED:
- canceled = True
- log.debug("Cancel pressed!")
- except Queue.Empty:
- break
-
- return canceled
-
- def write_queue(self, message):
- if self.update_queue is not None and message != self.prev_update:
- self.update_queue.put(message)
- time.sleep(0)
- self.prev_update = message
-